<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Setting up Relationships : DataMapper ORM - User Guide</title>

<link rel="shortcut icon" type="image/png" href="../images/favicon.png" />
<link rel="stylesheet" type="text/css" media="all" href="../css/userguide.css" />
<link rel="alternate" type="application/rss+xml" title="Datamapper ORM Updates Feed" href="/rss.xml" />

<meta http-equiv="expires" content="-1" />
<meta http-equiv= 'pragma' content="no-cache" />
<meta name="robots" content="all" />

</head>

<body>

<!-- START NAVIGATION -->
<div id="nav"><div id="nav_inner"></div></div>
<div id="nav2"><a name="top">&nbsp;</a><a id="nav_toggle" href="#"><img src="../images/nav_toggle_darker.jpg" width="154" height="43" border="0" title="Toggle Table of Contents" alt="Toggle Table of Contents" /></a></div>
<div id="masthead">
<table cellpadding="0" cellspacing="0" border="0" style="width:100%">
<tr>
<td><h1>DataMapper ORM</h1></td>
<td id="breadcrumb_right"><a href="toc.html">Table of Contents Page</a></td>
</tr>
</table>
</div>
<!-- END NAVIGATION -->

<!-- START BREADCRUMB -->
<table cellpadding="0" cellspacing="0" border="0" style="width:100%">
<tr>
<td id="breadcrumb">
<a href="/">Datamapper ORM Home</a> &nbsp;&#8250;&nbsp;
<a href="../index.html">User Guide Home</a> &nbsp;&#8250;&nbsp;
Setting up Relationships
</td>
</tr>

</table>
<!-- END BREADCRUMB -->

<br clear="all" />


<!-- START CONTENT -->
<div id="content">


<h1>Setting up Relationships</h1>

<p>In order for your DataMapper models to know the relationships it has between other DataMapper models, you need to set its <var><i>$has_one</i></var> and <var><i>$has_many</i></var> variables.  You do this by adding a class variable of <var><i>$has_one</i></var> and <var><i>$has_many</i></var>, both of which are arrays.</p>
<p>The values you add to these arrays is the related models name in lowercase. For example:</p>

<h3>User</h3>

<pre>
<kbd>class </kbd><var>User </var><kbd>extends </kbd><var><u>DataMapper</u> </var><kbd>{

    var </kbd><var><i>$has_one</i> </var><kbd>= array(</kbd><dfn>"country"</dfn><kbd>);

    function </kbd><var><dfn>__construct</dfn></var><kbd>(</kbd><var>$id </var><kbd>= </kbd><var>NULL</var><kbd>)
    {
        </kbd><var><dfn>parent</dfn></var><kbd>::</kbd><var><dfn>__construct</dfn></var><kbd>(</kbd><var>$id</var><kbd>);
    }
}

</kbd><samp>/* End of file user.php */
/* Location: ./application/models/user.php */</samp>
</pre>

<h3>Country</h3>
<pre>
<kbd>class </kbd><var>Country </var><kbd>extends </kbd><var><u>DataMapper</u> </var><kbd>{

    var </kbd><var><i>$table</i> </var><kbd>= </kbd><dfn>"countries"</dfn><kbd>;

    var </kbd><var><i>$has_many</i> </var><kbd>= array(</kbd><dfn>"user"</dfn><kbd>);

    function </kbd><var><dfn>__construct</dfn></var><kbd>(</kbd><var>$id </var><kbd>= </kbd><var>NULL</var><kbd>)
    {
        </kbd><var><dfn>parent</dfn></var><kbd>::</kbd><var><dfn>__construct</dfn></var><kbd>(</kbd><var>$id</var><kbd>);
    }
}

</kbd><samp>/* End of file country.php */
/* Location: ./application/models/country.php */</samp>
</pre>

<p>Looking above, we can see that a user can relate to only one country but a country can relate to many users. For example, I was born in the United States. It's not really possible for me to have been born in more than one country.  That's where the <var><i>$has_one</i></var> setting in the <var>User</var> model comes into play. The U.S. however has lots of people (or users in this example) which is where the <var><i>$has_many</i></var> setting in the <var>Country</var> model comes into play.</p>

<h2>Multiple Relations</h2>

<p>You can setup as many relationships as you need. You simply add more lowercase model names into the <var><i>$has_one</i></var> or <var><i>$has_many</i></var> variables as needed.</p>

<h3>User</h3>
<pre>
<var><i>$has_one</i> </var><kbd>= array(</kbd><dfn>"country"</dfn><kbd>, </kbd><dfn>"group"</dfn><kbd>);
</kbd><var><i>$has_many</i> </var><kbd>= array(</kbd><dfn>"book"</dfn><kbd>, </kbd><dfn>"setting"</dfn><kbd>);</kbd>
</pre>

<h2>Populating Related Objects</h2>

<p>By default, DataMapper does not auto populate your related objects when you first access them.  You have to populate them in much the same way you do your normal objects (read <a href="get.html">Get</a> for more information). For example:</p>

<pre>
<samp>// Create a Country object and get the record for Australia
</samp><var>$c </var><kbd>= new </kbd><var>Country</var><kbd>();
</kbd><var>$c</var><kbd>-&gt;</kbd><var><u>where</u></var><kbd>(</kbd><dfn>'name'</dfn><kbd>, </kbd><dfn>'Australia'</dfn><kbd>)-&gt;</kbd><var><u>get</u></var><kbd>();

</kbd><samp>// Populate the related users object with all related records
// Note: get_iterated is used because we are only looping over the users list once.
</samp><var>$c</var><kbd>-&gt;</kbd><var>user</var><kbd>-&gt;</kbd><var><u>get_iterated</u></var><kbd>();

</kbd><samp>// Loop through to see all related users
</samp><kbd>foreach (</kbd><var>$c</var><kbd>-&gt;</kbd><var>user</var> <kbd>as </kbd><var>$u</var><kbd>)
{
    echo </kbd><var>$u</var><kbd>-&gt;</kbd><var>username </var><kbd>. </kbd><dfn>'&lt;br /&gt;'</dfn><kbd>;
}</kbd>
</pre>

<p>An example of populating your related users with a more refined list could be paged results of users who are older than 18 years of age.</p>

<pre>
<samp>// Create a Country object and get the record for Australia
</samp><var>$c </var><kbd>= new </kbd><var>Country</var><kbd>();
</kbd><var>$c</var><kbd>-&gt;</kbd><var><u>where</u></var><kbd>(</kbd><dfn>'name'</dfn><kbd>, </kbd><dfn>'Australia'</dfn><kbd>)-&gt;</kbd><var><u>get</u></var><kbd>();

</kbd><samp>// How many related records we want to limit ourselves to
</samp><var>$limit </var><kbd>= </kbd><var>20</var><kbd>;

</kbd><samp>// The page we're looking at
</samp><var>$page </var><kbd>= </kbd><var>2</var><kbd>;

</kbd><samp>// Set the offset for our paging
</samp><var>$offset </var><kbd>= </kbd><var>$page </var><kbd>* </kbd><var>$limit</var><kbd>;

</kbd><samp>// Populate the related users object
</samp><var>$c</var><kbd>-&gt;</kbd><var>user</var><kbd>-&gt;</kbd><var><u>where</u></var><kbd>(</kbd><dfn>'age &gt;'</dfn><kbd>, </kbd><dfn>'18'</dfn><kbd>)-&gt;</kbd><var><u>get_iterated</u></var><kbd>(</kbd><var>$limit</var><kbd>, </kbd><var>$offset</var><kbd>);

</kbd><samp>// Loop through to see all related users matching our related query above
</samp><kbd>foreach (</kbd><var>$c</var><kbd>-&gt;</kbd><var>user</var> <kbd>as </kbd><var>$u</var><kbd>)
{
    echo </kbd><var>$u</var><kbd>-&gt;</kbd><var>username </var><kbd>. </kbd><dfn>'&lt;br /&gt;'</dfn><kbd>;
}</kbd>
</pre>


<h2 id="Automatic.Population">Automatic Population of Related Objects</h2>
<p>Now, if you'd prefer your related objects are auto populated when you first access them, you can do so by setting the <var><i>$auto_populate_has_many</i></var> and <var><i>$auto_populate_has_one</i></var> class variables in your DataMapper models to TRUE or by setting them to TRUE in the DataMapper <a href="config.html">Configuration</a>.  Obviously these will auto populate their respective relation type.</p>

<pre>
<kbd>var </kbd><var>$auto_populate_has_many </var><kbd>= </kbd><var><dfn>TRUE</dfn></var><kbd>;
var </kbd><var>$auto_populate_has_one </var><kbd>= </kbd><var><dfn>TRUE</dfn></var><kbd>;</kbd>
</pre>

<p>With your model set to auto populate "has many" and/or "has one" related objects, you can go directly to looping through the related objects. For example:</p>
<pre>
<samp>// Create a Country object and get the record for Australia
</samp><var>$c </var><kbd>= new </kbd><var>Country</var><kbd>();
</kbd><var>$c</var><kbd>-&gt;</kbd><var><u>where</u></var><kbd>(</kbd><dfn>'name'</dfn><kbd>, </kbd><dfn>'Australia'</dfn><kbd>)-&gt;</kbd><var><u>get</u></var><kbd>();

</kbd><samp>// Loop through to see all related users
</samp><kbd>foreach (</kbd><var>$c</var><kbd>-&gt;</kbd><var>user</var> <kbd>as </kbd><var>$u</var><kbd>)
{
    echo </kbd><var>$u</var><kbd>-&gt;</kbd><var>username </var><kbd>. </kbd><dfn>'&lt;br /&gt;'</dfn><kbd>;
}</kbd>
</pre>

<p>The only downside of auto populating is that it will populate with all related records.  So, looking at the above example, if we had a hundred thousand users related to Australia, all of those users would have to be read from the Database and loaded into memory, which is not good for performance, and why it is recommended you stick to manually populating with sensibly defined query clauses.</p>


</div>
<!-- END CONTENT -->


<div id="footer">
<p>
<span id="footer_previous">Previous Topic:&nbsp;&nbsp;<a href=""></a>
&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;</span>
<a href="#top">Top of Page</a>&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
<a href="../index.html">User Guide Home</a>
<span id="footer_next">&nbsp;&nbsp;&nbsp;&middot;&nbsp;&nbsp;
Next Topic:&nbsp;&nbsp;<a href=""></a></span>
</p>
<div id="copyrights">
<p><a href="/">Datamapper ORM</a> &nbsp;&middot;&nbsp; Copyright &copy; 2010-2011 &nbsp;&middot;&nbsp; Harro "WanWizard" Verton</p>
<p><a href="license.html">Other License Information</a></p>
</div>
</div>

<script type="text/javascript" src="../js/mootools.js"></script>
<script type="text/javascript" src="../js/menu.js"></script>
<script type="text/javascript">
<!--
	window.addEvent('domready', function() {

		// Create Menu
		var menu = new Menu({
			basepath: '../',
			pagespath: ''
		});

	});
//-->
</script>
</body>
</html>
